﻿using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

namespace AutoUpdateB
{
    internal class AsyncDownloader
    {
        private HttpClient _client;
        private CancellationTokenSource _cts;
        private long _receivedBytes;
        private bool _isResuming;   //是否支持断点续传

        public static Task<string> DownloadString(string url)
        {
            WebClient client = new WebClient();
            client.Encoding = System.Text.Encoding.UTF8;
            return client.DownloadStringTaskAsync(url);
        }

        /// <summary>
        /// 下载进度变更事件
        /// </summary>
        public event EventHandler<DownloadProgressArgs> ProgressChanged;

        public AsyncDownloader()
        {
            _client = new HttpClient
            {
                Timeout = TimeSpan.FromMinutes(30) // 长连接超时设置
            };
        }


        /// <summary>
        /// 启动异步下载任务
        /// </summary>
        /// <param name="url">文件URL</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="resumeDownload">是否启用断点续传</param>
        /// <param name="total">总大小</param>
        public async Task StartDownloadAsync(string url, string savePath,bool resumeDownload = false)
        {

            _cts = new CancellationTokenSource();
            _isResuming = resumeDownload;

            try
            {
                // 提取文件目录
                string directoryPath = Path.GetDirectoryName(savePath);
                if (!string.IsNullOrEmpty(directoryPath))
                {
                    // 创建目录
                    Directory.CreateDirectory(directoryPath);
                }
                Directory.CreateDirectory(directoryPath);
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);

                if (_isResuming)
                {
                    long existingFileSize = GetExistingFileSize(savePath);
                    if (existingFileSize > 0)
                    {
                        request.Headers.Range = new RangeHeaderValue(existingFileSize, null);
                        _receivedBytes = existingFileSize;
                    }
                }

                HttpResponseMessage response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, _cts.Token);
                response.EnsureSuccessStatusCode();

                await ProcessResponse(response, savePath);
            }
            catch (OperationCanceledException)
            {
                // 处理用户取消逻辑
            }
        }


        /// <summary>
        /// 处理HTTP响应流
        /// </summary>
        private async Task ProcessResponse(HttpResponseMessage response, string savePath)
        {
            _receivedBytes = GetExistingFileSize(savePath);

            using (var stream = await response.Content.ReadAsStreamAsync())
            using (var fileStream = new FileStream(
                savePath,
                _isResuming ? FileMode.Append : FileMode.Create,
                FileAccess.Write))
            {
                var buffer = new byte[8192 * 4]; // 32KB缓冲区
                int bytesRead;

                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cts.Token)) > 0)
                {
                    await fileStream.WriteAsync(buffer, 0, bytesRead, _cts.Token);
                    _receivedBytes = bytesRead;
                    ReportProgress();
                }
            }
        }

        /// <summary>
        /// 触发进度更新事件
        /// </summary>
        private void ReportProgress()
        {
            ProgressChanged?.Invoke(this, new DownloadProgressArgs
            {
                ReceivedBytes = _receivedBytes,
            });
        }

        private long GetExistingFileSize(string path)
        {
            if (File.Exists(path))
            {
                return new System.IO.FileInfo(path).Length;
            }
            return 0;
        }

  
}

    /// <summary>
    /// 下载进度事件参数
    /// </summary>
    public class DownloadProgressArgs : EventArgs
    {
        public long ReceivedBytes { get; set; }
    }

}
